/*
Copyright 2010 SGSL

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package com.dataiti.sgsl.layer;

import java.awt.Color;
import java.awt.Font;
import java.util.HashMap;
import java.util.Map;
import com.dataiti.sgsl.ISGSL;
import com.dataiti.sgsl.globe.SGSLGlobe;
import com.jhlabs.map.layer.Feature;
import com.jhlabs.map.layer.Layer;
import com.jhlabs.map.layer.PointFeature;
import com.jhlabs.map.layer.Style;
import com.jhlabs.map.proj.AzimuthalProjection;
import com.jhlabs.map.proj.Ellipsoid;
import com.jhlabs.map.proj.Projection;



/**
 * This class implements ISGSL interface which 
 * gives implementation for the operations to be performed on the globe 
 *
 */
public class SGSL implements ISGSL {
	
	private SGSLGlobe objGlobe = null;
	private float drawPositionLat ;
	private float drawPositionLon ;
	private Color objColor =  ISGSL.red;
	private int labelSize = 20;
	private double centreLat;
	private double centreLon;
	private Map objRadiusDegreeMap;
    
	private SGSL() {
		objGlobe = new SGSLGlobe();
		objRadiusDegreeMap = new HashMap();
		init();
	}
	
	
	/**
	 * Factory for creation of SGSL library.
	 * @return
	 */
	public static SGSL create() {
		return new SGSL();
	}

   
	/**
	 * display arc of great circle connecting two points.
	 * 
	 * @param startLat
	 * @param startLon
	 * @param endLat
	 * @param endLon
	 */
	public void drawArc( double startLat,double startLon, 
			             double endLat,double endLon) {
		Layer editLayer = new Editlayer((float)startLon,(float)startLat,(float)endLon,(float)endLat,SGSLConstants.CMD_LINE,objColor);	
        objGlobe.setLayer(editLayer); 
    }

   
	public void drawArc(double angle, double length) {
		// TODO Auto-generated method stub

	}
	
	/**
	 * display empty circle centered at current position
	 * 
	 * @param radius
	 */
	public void drawCircle(double radius) {
		
		Layer editLayer = new Editlayer(drawPositionLon,drawPositionLat,radius,SGSLConstants.CMD_CIRCLE,objColor);	
        objGlobe.setLayer(editLayer);        
	}
    
	
	
	/**
	 * display string as a label at current position on the illustration (First
	 * character displays 2 millimeteres to the right of the position to avoid
	 * being right on top of the position.)
	 * 
	 * @param string
	 */
	public void drawLabel(String string) {
		Feature textFeature;		
		Style pointStyle = new Style();
		pointStyle.setFont( new Font( "sansserif", Font.PLAIN,labelSize ) );
		pointStyle.setTextPaint( objColor);
		pointStyle.setTextSize( labelSize);
		pointStyle.setScaleText( false );
		textFeature = new PointFeature(drawPositionLon,drawPositionLat,string,pointStyle);
		objGlobe.setFeature(textFeature);	
		
	}

    
	
	/**
	 * display a point(circle) centered at current position
	 * 
	 * @param radius
	 */
	public void drawPoint() {
		Layer editLayer = new Editlayer(drawPositionLon,drawPositionLat,SGSLConstants.DEFAULT_POINT_RADIUS,SGSLConstants.CMD_CIRCLE,objColor);
        objGlobe.setLayer(editLayer);  

	}

   /**
    * Erases the entire graphics and its associated object like circle,line,point,arc
    */
	public void eraseGraphic() {
		objGlobe = new SGSLGlobe();
		init();
	}

   /**
	 * print a message on the lower panel of the applet. On screen - grows a
	 * scroll bar if there are lots of messages. Font and size are as would be
	 * created by default by System.out.println().
	 * 
	 * @param string
	 */
	public void printMessage(String string) {
		objGlobe.setPrintLabel(string);

	}

    
	/**
	 * print applet on paper. The usual platform-dependent print dialog should
	 * help select the printer which can be any kind of printing device
	 * supporting standard paper sizes (US Letter required at minimum). There
	 * should be nothing stopping the user from printing to a PDF writer so they
	 * get a file they can easily save, email as an attachment, etc. The print
	 * out would include the graphic illustration, and the message panel below
	 * it, continuing on additional pages to fit all messages.
	 */
	public void printPage() {
		objGlobe.print();
	}
   
	
	/**
	 * illustration is centered at this lat and lon. North pole is always top
	 * center if not on the graphic, and on a vertical centerline of the graphic
	 * if it appears on the graphic.
	 * 
	 * @param lat
	 * @param lon
	 */
	public void setCenter( double lat,double lon) {		
		
		centreLat = lat;
		centreLon = lon;
		
		Projection objProjection = objGlobe.getProjection();
		objProjection.setProjectionLatitudeDegrees(lat);
		objProjection.setProjectionLongitudeDegrees(lon);		
		
		objProjection.initialize();
		objGlobe.repaint();
	}

	/**
	 * change current color. Color code is an instance of an enum void Color
	 * having values specified below. Applies to both text and lines.
	 * 
	 * @param color
	 */
	public void setColor(Color color) {
		this.objColor = color;

	}

    
	
	/**
	 * set current drawing position to lat and lon
	 * 
	 * @param lat
	 * @param lon
	 */
	public void setDrawingPosition(double lat,double lon) {
		this.drawPositionLon =(float)lon;
		this.drawPositionLat =(float)lat;
	}

    
	
	/**
	 * sets size of text displayed on illustration. This is NOT a font size. It is
	 * measured as a fraction of the graphical panel size. Example 0.05 means
	 * the letters are about 5% of the height of the entire graphical panel.The maximum
	 * textHeightFraction is limited to 0.10.
	 * 
	 * @param textHeightFraction
	 */
	public void setLabelSize(double textHeightFraction) {
	    // checking maximum percentage
		
		if (textHeightFraction > SGSLConstants.MAX_TEXT_HEIGHT_FRACTION)
		{
			textHeightFraction = SGSLConstants.MAX_TEXT_HEIGHT_FRACTION;
		}
		
		labelSize = (int)(textHeightFraction * objGlobe.getHeight());
				
		if (labelSize ==0)
		{
			labelSize =10;
		}

	}
    
	
	/**
	 * Width and height of illustration (that is, it is zoomed to show this much
	 * of the earth).
	 * 
	 * @param sz
	 *            The width and height are both given by this single parameter
	 *            in decimal degrees.
	 */
	
	public void setWidthAndHeight(double sz) {
		
		if (sz > 180)
		{
			System.out.println("Max value exceeded setting to limit" + 180);
			sz= 180;
		}
		Projection projection = objGlobe.getProjection();
		AzimuthalProjection p = ((AzimuthalProjection) projection);
		String tmpRadius = String.valueOf(sz);
		Object obj = objRadiusDegreeMap.get(tmpRadius);
		if (obj != null)
		{
			double newRadius = Double.parseDouble((String)obj);
			p.setEllipsoid(new Ellipsoid("", newRadius, newRadius, 0, ""));
			projection.initialize();
			objGlobe.repaint();
		}
		else
		{
			System.out.println("Null value got for  "+sz);
		}	
	}
	
	/**
	 * 
	 * @return objGlobe - Reference of the Globe object returned.
	 */
	public SGSLGlobe getGlobe(){
	   return objGlobe;	   
	}
	
	/**
	 *This method will be invoked when the new Globe is created.
	 *This will initalize center and drawing position
	 *
	 */
	private void init()
	{
		setCenter(SGSLConstants.DEFAULT_CENTER_LONGTITUDE,SGSLConstants.DEFAULT_CENTER_LATITUDE);
		setDrawPositionLon (SGSLConstants.DEFAULT_CENTER_LONGTITUDE);
		setDrawPositionLat(SGSLConstants.DEFAULT_CENTER_LATITUDE);
		getRadius();
	}

	 /**
     * This method returns latitude drawing position
     * 
     * @return Latitude drawing position in degrees
     */	
	public float getDrawPositionLat() {
		return drawPositionLat;
	}

	/**
	  * This method sets Latitude drawing position 
	  * @param drawPositionLat - Latitude position in degrees
	 */
	public void setDrawPositionLat(float drawPositionLat) {
		this.drawPositionLat = drawPositionLat;
	}

    
	
    /**
     * This method returns Longitude drawing position
     * 
     * @return Longitude drawing position in degrees
     */	
	public float getDrawPositionLon() {
		return drawPositionLon;
	}

   /**
    * This method sets Longitude drawing position 
    * @param drawPositionLon - Longitude position in degrees
    */
	public void setDrawPositionLon(float drawPositionLon) {
		this.drawPositionLon = drawPositionLon;
	}

	/**
	 * displays the continent & country boundary map.
	 * @param visible - Boolean flag to set on/off
	 */
	public void setBackground(boolean visible) {
		objGlobe.setShowWorld(visible);
		objGlobe.repaint();
		
	}
	
	
	/**
	 * displays the grid lines of the projection
	 * @param visible - Boolean flag to set on/off
	 */
	public void setGridLines(boolean visible) {
		objGlobe.setShowGraticule(visible);
		objGlobe.repaint();		
	}
	
	
	/**
	 * This method lookup radiusLookup.value file to get radius,degree values
	 *
	 */
	private void getRadius()
	{
	    new InitRadiusLookup().getRadius(objRadiusDegreeMap);
	}
	
	public static void main(String args[])
	{
		new SGSL().getRadius();
	}



	/**
	 * display filled circle centered at current position
	 * 
	 * @param radius
	 */
	public void drawFilledCircle(double radius) {
		Layer editLayer = new Editlayer(drawPositionLon,drawPositionLat,radius,SGSLConstants.CMD_FILLEDCIRCLE,objColor);	
        objGlobe.setLayer(editLayer); 
		
		
	}

}
